/**
 * @Title: ChangChengChuKouDataProcess.java
 * @Package tbg 
 * @Description: TODO
 * @author tbc
 * @date 2016年6月9日 上午12:39:34
 * @version
 */
package tbg;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.google.common.collect.Lists;

import lombok.Data;

/**
 * 其实应该是列转行，迷糊了。。。<br>
 * h:\\Users\\tbc\\Desktop\\中兴1605原始 - 副本.xlsx <br>
 * h:\\Users\\tbc\\Desktop\\庆铃1606原始.xlsx
 * h:\\Users\\tbc\\Desktop\\长城1606原始-出口.xlsx
 * 
 * @author tbc
 * @version 1.0 create:{2016年6月9日 上午12:39:34}
 * 
 */
public class Row2Column {

	private static int staticRows = 3;// 长城
	private static int staticColumns = 4;// 长城

	private static XSSFWorkbook book = null;
	private static XSSFSheet sheet = null;

	private static double toDouble(String source) {
		return toDouble(source, 0.0);
	}

	private static double toDouble(String source, Double def) {
		try {
			return Double.parseDouble(source);
		} catch (Exception e) {
			return def;
		}
	}

	public static void main(String[] args) throws InterruptedException {
		if ("zhongxing".equals(args[0])) {
			staticRows = 1;
			staticColumns = 2;
			System.out.println("中兴...");
		} else if ("normal".equals(args[0])) {
			System.out.println("通用...");
			System.out.println("输入固定的行数：");
			Scanner ss = new Scanner(System.in);
			String _r = ss.nextLine();
			staticRows = Integer.parseInt(_r);
			System.out.println("输入固定的列数：");
			String _c = ss.nextLine();
			staticColumns = Integer.parseInt(_c);
		}

		System.out.println("拖动待处理的文件到当前窗口：");
		@SuppressWarnings("resource")
		Scanner s = new Scanner(System.in);
		String from = s.nextLine();
		System.out.println("初始化 ...");
		// 初始化
		init(from);
		System.out.println("初始化完成");
		System.out.println("读取并处理数据...");
		List<List<String>> datas = readExcel();
		System.out.println("读取完成...处理完成...\n正在生成新的sheet页\"整理\"");
		// write
		write(datas);

		System.out.println("新的sheet页\"整理\"创建完成...\n正在写到Excel文件...");
		OutputStream out = null;
		try {
			out = new FileOutputStream(from);
			book.write(out);
		} catch (FileNotFoundException e) {
			System.out.println("创建输出流失败 ：" + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("写Excel失败 ： " + e.getMessage());
			e.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		System.out.println("完成");
		TimeUnit.SECONDS.sleep(1);

	}

	public static void init(String from) throws InterruptedException {
		if (from.startsWith("\"")) {
			System.out.println("文件路径带引号，尝试去除...");
			from = from.substring(1, from.length() - 1);
		}
		System.out.println("正在加载文件：" + from);

		InputStream in = null;
		try {
			in = new FileInputStream(from);
			System.out.println("加载成功，创建工作簿对象...");
			book = new XSSFWorkbook(in);
			System.out.println("工作簿对象创建完成");
		} catch (FileNotFoundException e) {
			System.out.println("读取文件失败，文件不存在或者文件名有特殊符号。。。最好是只有英文字母");
			System.out.println("程序自动退出，修改文件路径或者文件名再试试");
			TimeUnit.SECONDS.sleep(2);
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("加载excel失败，不知道为什么 ，程序退出。。。");
			System.out.println(e.getMessage());
			TimeUnit.SECONDS.sleep(2);
		}
		System.out.println("读取sheet页\"1\"");
		try {
			sheet = book.getSheet("1");
			if (sheet == null) {
				System.out.println("读取sheet页\"1\"失败，检查是否存在该sheet页");
				TimeUnit.SECONDS.sleep(2);
				System.exit(0);
			}
		} catch (Exception e) {
			System.out.println();
		}

	}

	/**
	 * 
	 * @author tbc
	 * @version 1.0 create:{2016年7月2日 下午3:20:13}
	 * 
	 * @update 2016年07月02日 15:20:24
	 * @问题 待转列的行，头信息，缓存在了外层循环外之外，在方法内相当于全局变量，某列值为0或Null时，缓存了该列的头，但因为值为空，
	 *     未走到清空缓存就退出循环，待到下个有值的单元格，缓存已积攒很多
	 * @修正 将缓存移到最内层循环，生命周期只存在于当前列
	 */
	public static List<List<String>> readExcel() {
		List<List<String>> result = new ArrayList<>();

		// 要转列的行
		List<XSSFRow> rows = new ArrayList<>();
		for (int i = 0; i < staticRows; i++) {
			rows.add(sheet.getRow(i));
		}

		// 临时缓存头数据 - 必须定义在外层循环外，内层控制加一个删一个，保持size，跟行数相等
		// List<String> c = new ArrayList<>();
		List<MyOptional<String>> myCatch = Lists.newArrayList();

		for (int i = 0; i < staticRows; i++) {
			myCatch.add(new MyOptional<String>());
		}

		for (int i = staticRows; i <= sheet.getLastRowNum(); i++) {
			System.out.println("read row :" + i);

			XSSFRow row = sheet.getRow(i);
			for (int j = staticColumns; j < row.getLastCellNum(); j++) {
				System.out.println("read column : " + j);
				XSSFCell cell = row.getCell(j);
				//
				if (cell == null || cell.getRawValue() == null)
					continue;
				if (cell.getRawValue().equals("0") || cell.getRawValue().equals("0.0")) {
					continue;
				}

				// 将该列的“头数据”加入到行转列缓存 - 行转列缓存跟清空
				for (int x = 0; x < staticRows; x++) {
					XSSFRow xrow = rows.get(x);
					// if (xrow.getCell(j).getRawValue() != null) {
					// c.add(getHeadRowValue(xrow, x));
					// }
					myCatch.get(x).set(getHeadRowValue(xrow, j));
				}

				List<String> temp = new ArrayList<>();

				// 前几列加上
				for (int y = 0; y < staticColumns; y++) {
					XSSFCell _cell = row.getCell(y);
					if (null == _cell) {
						temp.add(null);
						// } else if (cell.getCellType() == 1) {// String类型
						// temp.add(row.getCell(y).getStringCellValue());
					} else {
						if (_cell.getCellType() == 1) // String类型
							temp.add(row.getCell(y).getStringCellValue());
						else
							temp.add(row.getCell(y).getRawValue());

					}

				}

				// 紧跟由行转过来的几列
				for (int z = 0; z < staticRows; z++) {
					temp.add(myCatch.get(z).get());
				}

				// 最后才是真正的数据,即数量
				temp.add(Double.valueOf(cell.getNumericCellValue()).toString());
				// c.clear();
				result.add(temp);
			}
		}

		return result;
	}

	public static void write(List<List<String>> datas) {
		XSSFSheet mySheet = book.createSheet("整理");

		// 向book对象中写数据
		for (int i = 0; i < datas.size(); i++) {
			XSSFRow row = mySheet.createRow(i);
			List<String> ds = datas.get(i);
			for (int j = 0; j < ds.size(); j++) {
				XSSFCell cell = row.createCell(j);
				if (j != (ds.size() - 1)) {
					cell.setCellValue(ds.get(j));
				} else {
//					String v = ds.get(j);
//					double value = Double.parseDouble(v);
					cell.setCellValue(toDouble(ds.get(j)));
				}

			}
		}
	}

	public static String getHeadRowValue(XSSFRow row, int x) {
		// 先找row行的x列，如果为空，x-1往前找，一直到找着，或者第staticColumns列，一直找不到，空着

		for (int i = x; i >= staticColumns; i--) {
			XSSFCell cell = row.getCell(i);
			if (cell == null || cell.getRawValue() == null)
				continue;
			return cell.getStringCellValue();
		}
		return null;
	}

}

/**
 * 不考虑线程安全，单用户
 * 
 * @ClassName: MyOptional
 * @Description: TODO
 * @author tbc
 * @date 2016年7月7日 下午11:58:03
 *
 */
class MyOptional<T> {

	private T value;

	static MyOptional empty() {
		return new MyOptional();
	}

	public T get() {
		return value;
	}

	public void set(T t) {
		value = t;
	}
}
